<template>
  <el-dialog title="版本对比" :visible.sync="dialogVisible" fullscreen :before-close="handleClose">
    <div class="wrapper">
      <div class="left left-wrapper">
        <div class="version current">当前版本</div>
        <div class="doc" ref="leftWrapperRef">
          <PreviewPage :pageList="currentPageList" container=".left-wrapper" />
        </div>
      </div>
      <div class="right right-wrapper">
        <div class="version history">
          历史版本
          <el-select v-model="sourceDocNo" placeholder="请选择" size="small">
            <el-option
              v-for="item in historyList"
              :key="item.docNo"
              :value="item.docNo"
              :label="`${item.docName} ${item.standardVersion}`"
            >
            </el-option>
          </el-select>
          <el-button style="margin-left: 5px" type="primary" size="small" @click="handleConfirm">对比</el-button>
        </div>
        <div class="doc" ref="rightWrapperRef">
          <PreviewPage :pageList="historyPageList" container=".right-wrapper" />
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script>
import { compare, fetchData, fetchHistory } from '@/api'
import { StdPage } from '@/utils/parse/page'
import PreviewPage from '../PreviewPage.vue'
import { removeAllClass, syncScroller } from '@/utils/dom'
import { getContentListById, alignCompareList } from '@/utils/helpers'
import tinymce from 'tinymce/tinymce'

export default {
  name: 'VersionsCompareDialog',
  components: { PreviewPage },
  data() {
    return {
      scrollEvent: null,
      sourceDocNo: '',
      adds: [],
      removes: [],
      replaces: [],
      currentPageList: [],
      historyPageList: [],
      dialogVisible: false
    }
  },
  computed: {
    historyList() {
      return this.$store.state.xmleditor.historyList.filter(
        (i) => i.docNo !== this.$store.state.xmleditor.editorConfig.docNo
      )
    }
  },
  methods: {
    async show() {
      this.dialogVisible = true
      this.sourceDocNo = ''
      this.historyPageList = []
      await fetchHistory()
      const data = await fetchData()
      this.currentPageList = JSON.parse(data.data.jsonContent).pageList?.map((i) => new StdPage(i)) || []
      this.$nextTick(removeAllClass)
    },
    async handleConfirm() {
      if (!this.sourceDocNo) return
      removeAllClass()
      const sourceData = await fetchData(this.sourceDocNo)
      this.historyPageList = JSON.parse(sourceData.data.jsonContent).pageList?.map((i) => new StdPage(i)) || []

      const { data } = await compare({
        sourceDocNo: this.sourceDocNo,
        targetDocNo: this.$store.state.xmleditor.editorConfig.docNo
      })
      const [listA, listB, diff1, diff2, allPageIdList] = alignCompareList(this.currentPageList, this.historyPageList)
      this.currentPageList = listA
      this.historyPageList = listB
      this.scrollEvent = syncScroller(this.$refs.leftWrapperRef, this.$refs.rightWrapperRef)

      /** 左侧删除 */
      data.addList.forEach((id) => {
        const block = document.querySelector(`.left-wrapper [data-block-id="${id}"]`)
        const page = document.querySelector(`.left-wrapper [data-page-id="${id}"]`)
        // 1. 如果page已经有，block不加样式
        if (block && tinymce.DOM.is(tinymce.DOM.getParent(block, '.page-sheet'), '.compare-add, .compare-remove')) {
          return
        }
        if (page) {
          // 2. 如果block已经有，移除block加到page上
          ;[...page.querySelectorAll('compare-remove')].forEach((node) => node?.classList?.remove('compare-remove'))
        }
        ;(page || block)?.classList?.add('compare-remove')

        // 图注、图脚注
        const figureNote = document.querySelector(`.left-wrapper [data-note-id="${id}"]`)
        if (figureNote) {
          figureNote?.classList?.add('compare-remove')
        }
        // 列项
        const itemlistDom = document.querySelector(`.left-wrapper .item_list[data-id="${id}"]`)
        if (itemlistDom) itemlistDom?.classList?.add('compare-remove')
      })

      /** 右侧新增 */
      data.removeList.forEach((id) => {
        const block = document.querySelector(`.right-wrapper [data-block-id="${id}"]`)
        const page = document.querySelector(`.right-wrapper [data-page-id="${id}"]`)
        if (block && tinymce.DOM.is(tinymce.DOM.getParent(block, '.page-sheet'), '.compare-add, .compare-remove')) {
          return
        }
        if (page) {
          ;[...page.querySelectorAll('compare-add')].forEach((node) => node?.classList?.remove('compare-add'))
        }
        ;(page || block)?.classList?.add('compare-add')

        // 图注、图脚注
        const figureNote = document.querySelector(`.right-wrapper [data-note-id="${id}"]`)
        if (figureNote) {
          figureNote?.classList?.add('compare-add')
        }
        // 列项
        const itemlistDom = document.querySelector(`.right-wrapper [data-id="${id}"]`)
        if (itemlistDom) itemlistDom?.classList?.add('compare-add')
      })

      /** 左右两侧的修改 */
      data.changeList.forEach((item) => {
        const blockId = item.uid.indexOf(':') === -1 ? item.uid : item.uid.match(/(\S*):/)[1]
        const leftBlock = document.querySelector(`.left-wrapper [data-id="${blockId}"]`)
        const rightBlock = document.querySelector(`.right-wrapper [data-id="${blockId}"]`)

        if (leftBlock?.dataset?.type === 'formula' || leftBlock?.dataset?.type === 'figure') {
          leftBlock?.classList?.add('compare-remove')
          rightBlock?.classList?.add('compare-add')
          return
        }

        const leftContentList = getContentListById(this.currentPageList, blockId)?.map((i) => i.contentType)
        const rightContentList = getContentListById(this.historyPageList, blockId)?.map((i) => i.contentType)
        if (['data-content-image-caption', 'table_caption'].some((i) => leftBlock?.classList?.contains(i))) {
          // 修改了图题或表题
          if (leftBlock && rightBlock) {
            let html = ''
            const diffList = item.textDiffList
            for (let index = 0; index < diffList.length; index++) {
              const i = diffList[index]
              if (i.operation === 'add') {
                html += `<span class="compare-remove">${i.text}</span>`
              } else if (i.operation === 'remove') {
                rightBlock.innerHTML = `<span class="compare-add">${i.text}</span>`
              } else if (i.operation === 'equals') {
                html += `${i.text}`
              }
            }
            leftBlock.innerHTML = html
          }
          return
        }
        if (rightBlock) {
          let html = ''
          for (let idx = 0; idx < item.leftTextDiffList.length; idx++) {
            const diffList = item.leftTextDiffList[idx]
            for (let index = 0; index < diffList.length; index++) {
              const contentType = leftContentList[idx] || 'text'
              if (contentType === 'sup') {
                html += '<sup data-type="sup">'
              } else if (contentType === 'sub') {
                html += '<sub data-type="sub">'
              }

              const i = diffList[index]
              if (i.operation === 'equals') {
                html += i.text
              } else if (i.operation === 'add') {
                html += `<span class="compare-add">${i.text}</span>`
              } else if (i.operation === 'remove') {
                html += `<span class="compare-remove">${i.text}</span>`
              }
              if (contentType === 'sup') {
                html += '</sup>'
              }
              if (contentType === 'sub') {
                html += '</sub>'
              }
            }
          }

          rightBlock.innerHTML = html
        }

        if (leftBlock) {
          let html = ''
          for (let idx = 0; idx < item.rightTextDiffList.length; idx++) {
            const diffList = item.rightTextDiffList[idx]
            for (let index = 0; index < diffList.length; index++) {
              const contentType = rightContentList[idx] || 'text'
              if (contentType === 'sup') {
                html += '<span data-type="sup">'
              } else if (contentType === 'sub') {
                html += '<span data-type="sub">'
              }

              const i = diffList[index]
              if (i.operation === 'equals') {
                html += i.text
              } else if (i.operation === 'remove') {
                html += `<span class="compare-remove">${i.text}</span>`
              } else if (i.operation === 'add') {
                html += `<span class="compare-add">${i.text}</span>`
              }
              if (contentType === 'sup' || contentType === 'sub') {
                html += '</span>'
              }
            }
          }

          leftBlock.innerHTML = html
        }
      })

      setTimeout(() => {
        ;[...diff1, ...diff2].forEach((id) => {
          const pageL = document.querySelector(`.left-wrapper [data-page-id="${id}"]`)
          const pageR = document.querySelector(`.right-wrapper [data-page-id="${id}"]`)
          pageL?.classList?.remove('compare-remove')
          pageL?.classList?.remove('compare-add')
          pageR?.classList?.remove('compare-remove')
          pageR?.classList?.remove('compare-add')
        })
        diff1.forEach((id) => {
          const pageL = document.querySelector(`.left-wrapper [data-page-id="${id}"]`)
          const pageR = document.querySelector(`.right-wrapper [data-page-id="${id}"]`)
          pageL?.classList?.add('page-compare-add')
          pageR?.classList?.add('page-compare-remove')
        })
        diff2.forEach((id) => {
          const pageL = document.querySelector(`.left-wrapper [data-page-id="${id}"]`)
          const pageR = document.querySelector(`.right-wrapper [data-page-id="${id}"]`)
          pageL?.classList?.add('page-compare-remove')
          pageR?.classList?.add('page-compare-add')
        })
        allPageIdList.forEach((id) => {
          const pageL = document.querySelector(`.left-wrapper [data-page-id="${id}"]`)
          const pageR = document.querySelector(`.right-wrapper [data-page-id="${id}"]`)
          // 封面页等为null
          if (pageL && pageR) {
            const rectL = pageL.getBoundingClientRect()
            const rectR = pageR.getBoundingClientRect()
            const heightL = rectL.height
            const heightR = rectR.height
            const max = Math.max(heightR, heightL)
            if (max !== heightL) {
              pageL.style.height = max + 'px'
            }
            if (max !== heightR) {
              pageR.style.height = max + 'px'
            }
          }
        })
      })
    },
    handleClose() {
      this.dialogVisible = false
    }
  },
  beforeMount() {
    if (this.scrollEvent) this.scrollEvent()
  }
}
</script>

<style scoped>
.wrapper {
  display: flex;
  height: calc(100vh - 65px);
}
.left,
.right {
  flex: 1;
  margin-left: 5px;
  width: 50%;
  display: flex;
  flex-direction: column;
}
.doc {
  overflow: scroll;
  flex: 1;
  border: 1px solid #ccc;
}
.version {
  height: 32px;
  margin-bottom: 2px;
  vertical-align: middle;
  line-height: 32px;
}
::v-deep .el-dialog__body {
  color: #000;
  padding-top: 0;
  padding-bottom: 10px;
}
</style>
